﻿using System;
using System.IO;
using System.Collections.Generic;
using CsvHelper;

namespace AIC_Notification
{
    public class RallyOfRallySchoolStatistics
    {
        public RallySchoolStatistics[][] RallyOfStatistics;

        public RallyOfRallySchoolStatistics()
        {
            Reset_RallyOfRallySchoolStatistics();
        }

        public void Reset()
        {
            Reset_RallyOfRallySchoolStatistics();
        }

        public void Add(RallySchoolStatistics Statistics, int Rally, int SchoolNumber)
        {
            if (Rally < 0 || Rally > RallyHelper.NoOfRally)
            {
                Global.SysUtil.Log(String.Format("Invalid Rally {0} in RallySchoolStatistics:Add", Rally), 2);
                return;
            }

            if (SchoolNumber < 0 || SchoolNumber > SOF_Application.MAX_SCHOOL_IN_RALLY)
            {
                Global.SysUtil.Log(String.Format("Invalid School # {0} in RallySchoolStatistics:Add", SchoolNumber), 2);
                return;
            }

            RallyOfStatistics[Rally][SchoolNumber] = Statistics;
        }

        public RallySchoolStatistics Get(int Rally, int SchoolNumber)
        {
            if (Rally < 0 || Rally > RallyHelper.NoOfRally)
            {
                Global.SysUtil.Log(String.Format("Invalid Rally {0} in RallySchoolStatistics:Get", Rally), 2);
                return null;
            }

            if (SchoolNumber < 0 || SchoolNumber > SOF_Application.MAX_SCHOOL_IN_RALLY)
            {
                Global.SysUtil.Log(String.Format("Invalid School # {0} in RallySchoolStatistics:Get", SchoolNumber), 2);
                return null;
            }

            if (RallyOfStatistics[Rally] != null)
                return RallyOfStatistics[Rally][SchoolNumber];
            else
                return null;
        }

        private void Reset_RallyOfRallySchoolStatistics()
        {
            RallyOfStatistics = new RallySchoolStatistics[RallyHelper.NoOfRally + 1][]; // +1 because we have CEF as Rally 0
            for (int i = 0; i < RallyHelper.NoOfRally + 1; i++)
            {
                RallyOfStatistics[i] = new RallySchoolStatistics[SOF_Application.MAX_SCHOOL_IN_RALLY];
                for (int j = 0; j < SOF_Application.MAX_SCHOOL_IN_RALLY; j++)
                {
                    RallyOfStatistics[i][j] = null;
                }
            }
        }
    }

    public class RallySchoolStatistics
    {
        public string Name = "";
        public int Rally = -1;
        public int Total = 0;
        public int NotStarted = 0;
        public int InProgress = 0;
        public int Completed = 0;
        public int StatusRed = 0;
        public int StatusYellow = 0;
        public int StatusGreen = 0;

        public int NumberOfEssay = 0;
        public RallyEssayStatistics[] EssayStatistics = null;

        public RallySchoolStatistics(string name, int NoOfEssay, int rally)
        {
            Name = name;
            Rally = rally;
            NumberOfEssay = NoOfEssay;

            EssayStatistics = new RallyEssayStatistics[NumberOfEssay];
            for (int i = 1; i <= NumberOfEssay; i++)
            {
                EssayStatistics[i - 1] = new RallyEssayStatistics();
                EssayStatistics[i - 1].EssayNumber = i;
            }
        }
    }

    public class RallyEssayStatistics
    {
        public int EssayNumber = 0;
        private int TotalNumber = 0;
        private int SumTotalDraft = 0;
        private int MinDraft = 0;
        private int MaxDraft = 0;

        public int GetMaxDraft()
        {
            return MaxDraft;
        }

        public void SetMaxDraft(int DraftNumber)
        {
            if (DraftNumber > 0)
                MaxDraft = DraftNumber;
        }

        public int GetMinDraft()
        {
            return (MinDraft >= 0) ? MinDraft : 0;
        }

        public void SetMinDraft(int DraftNumber)
        {
            if (DraftNumber > 0)
                MinDraft = DraftNumber;
        }

        public void SumAverage(int DraftNumber)
        {
            if (DraftNumber > 0)
            {
                TotalNumber += 1;
                SumTotalDraft += DraftNumber;
            }
        }

        public double AverageDraft()
        {
            return TotalNumber > 0 ? (double)SumTotalDraft / (double)TotalNumber : 0;
        }
    }

    public class EssayStatistics
    {
        public Essay DraftObject;
        public Essay PendingDraftObject;
        public int EssayNumber = 0;
        public int LatestDraft = 0;
        public int RallyStatus = 0;
        public bool HasRevision = false;
        public bool IsFinal = false;
        public bool MetRallyGoal = false;
        public DateTime DraftAttachmentDate;
        public bool HasOverDuedDraft = false;
        public bool HasIssue = false;
        public bool MissingDueDate = false;
        public bool MissingFinalTag = false;
        public bool MissingAttachment = false;
        public bool HasRevisionPending = false;
        public TimeSpan PendingTimeSpan;

        public EssayStatistics()
        {
            DraftObject = null;
            PendingDraftObject = null;
        }
    }

    public class SchoolStatistics
    {
        public int NumberOfEssay = 0;
        public bool AllEssayGoalMet = true;
        private int TotalAssignedDraft = -1;
        private int TotalOverDuedDraft = -1;
        private int TotalPendingRevision = -1;
        private int TotalOverDuedRevision = -1;
        public int RallyStatus = -1;
        public int NumberOfLateEssay = 0;
        public IList<EssayStatistics> EssayStatisticsList;

        public SchoolStatistics()
        {
            EssayStatisticsList = new List<EssayStatistics>();
        }

        public int GetTotalAssignedDraft()
        {
            if (TotalAssignedDraft != -1)
                return TotalAssignedDraft;
            else
            {
                TotalAssignedDraft = 0;

                foreach (var EssayStats in EssayStatisticsList)
                {
                    if (EssayStats.PendingDraftObject!= null && EssayStats.PendingDraftObject.hasDueDate && !EssayStats.PendingDraftObject.hasDraftAttachment)
                        TotalAssignedDraft += 1;
                }

                return TotalAssignedDraft;
            }
        }

        public int GetTotalOverDuedDraft()
        {
            if (TotalOverDuedDraft != -1)
                return TotalOverDuedDraft;
            else
            {
                TotalOverDuedDraft = 0;

                foreach (var EssayStats in EssayStatisticsList)
                {
                    if (EssayStats.HasOverDuedDraft)
                        TotalOverDuedDraft += 1;
                }

                return TotalOverDuedDraft;
            }
        }

        public int GetTotalPendingRevision()
        {
            return GetTotalRevision(0, ref TotalPendingRevision);
        }

        public int GetTotalOverDuedRevision()
        {
            return GetTotalRevision(3, ref TotalOverDuedRevision);
        }

        private int GetTotalRevision(int DaysToOverdue, ref int Revision)
        {
            if (Revision != -1)
                return Revision;
            else
            {
                Revision = 0;

                foreach (var EssayStats in EssayStatisticsList)
                {
                    if (EssayStats.HasRevisionPending && (EssayStats.PendingTimeSpan.TotalDays >= DaysToOverdue) && !EssayStats.MissingDueDate)
                        Revision += 1;
                }

                return Revision;
            }
        }
    }

    public class SOF_SchoolEssayCompletionStatistics
    {
        public int CompletedSchools = 0;
        public int InProgressSchools = 0;
        public int BehindSchools = 0;
    }

    public class SOF_SchoolTypeStatistics
    {
        public int SupplimentSchool = 0;
        public int NonSupplimentSchool = 0;
        public int SuperReach = 0;
        public int Reach = 0;
        public int Match = 0;
        public int Safety = 0;
        public int Unknown = 0;
        public int UC_SuperReach = 0;
        public int UC_Reach = 0;
        public int UC_Match = 0;
        public int UC_Safety = 0;
        public int ReachAccepted = 0;
        public int SolidAccepted = 0;
        public int SafetyAccepted = 0;
    }

    public class SOF_ApplicationStatistics
    {
        public int SchoolInCurrentRally = 0;
        public int TotalAssignedDraft = -1;
        public int TotalOverDuedDraft = -1;
        public int TotalPendingRevision = -1;
        public int TotalOverDuedRevision = -1;
        public double ProgressScore = 0;
        public int NumberOfLateEssay = 0;
        public SOF_SchoolTypeStatistics SchoolTypeStats;
        public SOF_SchoolEssayCompletionStatistics SchoolEssayCompletionStats;

        public SOF_ApplicationStatistics()
        {
            SchoolTypeStats = new SOF_SchoolTypeStatistics();
            SchoolEssayCompletionStats = new SOF_SchoolEssayCompletionStatistics();
        }
    }

    public class AggregatedStatistics
    {
        public int TotalStudents = 0;
        public double AverageSchoolInRally = 0;
        public int TotalAssignedDraft = 0;
        public int TotalOverDuedDraft = 0;
        public int TotalPendingRevision = 0;
        public int TotalOverDuedRevision = 0;
        public double ProgressScore = 0;
    }
   
    static class Statistics
    {
        static public ApplicationType ApplicationType = ApplicationType.unsupported;
        static public RunType RunType = RunType.full;
        static public DateTime StartTime;
        static public DateTime EndTime;
        static public int TotalBoard = 0;
        static public int ProcessingBoard = 0;
        static public IList<RallySchoolStatistics> RallySchoolStatsList;
        static public RallyOfRallySchoolStatistics RallyOfRallySchoolStats;
        static public AggregatedStatistics ApplicationStats;

        static public void Initialize()
        {
            RallySchoolStatsList = new List<RallySchoolStatistics>();
            ApplicationStats = new AggregatedStatistics();
            RallyOfRallySchoolStats = new RallyOfRallySchoolStatistics();
        }

        static public void SaveStatisticsAsCSV()
        {
            string StatisticsDirectoryName = @".\\statistics";
            string CompanyStatsFileName = StatisticsDirectoryName + "\\"+ @"CompanyStatistics.csv";
            string TeacherStatsFileName = StatisticsDirectoryName + "\\" + @"TeacherStatistics.csv";

            if (!Directory.Exists(StatisticsDirectoryName))
                Directory.CreateDirectory(StatisticsDirectoryName);

            // Add Company Statistics

            if (!File.Exists(CompanyStatsFileName)) // Header
            {
                using (StreamWriter StatisticsStreamWriter = new StreamWriter(CompanyStatsFileName, append: true))
                {
                    // Statistics CSV
                    CsvWriter StatisticsCSV = new CsvWriter(StatisticsStreamWriter);

                    StatisticsCSV.WriteField("Date");
                    for (int i = 0; i < CityDB.NoOfCities; i++)
                        StatisticsCSV.WriteField(CityDB.GetCityName((CityDB.CityEnum)i));

                    StatisticsCSV.WriteField("Total");

                    StatisticsCSV.NextRecord();
                }
            }

            using (StreamWriter StatisticsStreamWriter = new StreamWriter(CompanyStatsFileName, append: true))
            {
                // Statistics CSV
                CsvWriter StatisticsCSV = new CsvWriter(StatisticsStreamWriter);

                StatisticsCSV.WriteField(String.Format("{0:d}", Global.Now()));
                foreach (var City in CityDB.Cities)
                    StatisticsCSV.WriteField(City.ApplicationStats.TotalOverDuedRevision);

                StatisticsCSV.WriteField(Statistics.ApplicationStats.TotalOverDuedRevision);

                StatisticsCSV.NextRecord();
            }

            // Add Teacher Statistics

            if (!File.Exists(TeacherStatsFileName)) // Header
            {
                using (StreamWriter StatisticsStreamWriter = new StreamWriter(TeacherStatsFileName, append: true))
                {
                    // Statistics CSV
                    CsvWriter StatisticsCSV = new CsvWriter(StatisticsStreamWriter);

                    StatisticsCSV.WriteField("Date");
                    foreach (var Teacher in TeacherDB.Teachers)
                        if (Teacher.Type.Equals("Academic Consultant") || Teacher.Type.Equals("Both"))
                            StatisticsCSV.WriteField(Teacher.Name);

                    StatisticsCSV.NextRecord();
                }
            }

            using (StreamWriter StatisticsStreamWriter = new StreamWriter(TeacherStatsFileName, append: true))
            {
                // Statistics CSV
                CsvWriter StatisticsCSV = new CsvWriter(StatisticsStreamWriter);

                StatisticsCSV.WriteField(String.Format("{0:d}", Global.Now()));
                foreach (var Teacher in TeacherDB.Teachers)
                    if (Teacher.Type.Equals("Academic Consultant") || Teacher.Type.Equals("Both"))
                        StatisticsCSV.WriteField(Teacher.ApplicationStats.TotalOverDuedRevision);

                StatisticsCSV.NextRecord();
            }

        }
    }
}
